// -------------------------------------------------
// BlinKit - BlinKit Library
// -------------------------------------------------
//   File Name: page_popup_session.cpp
// Description: PagePopupSession Class
//      Author: Ziming Li
//     Created: 2022-05-15
// -------------------------------------------------
// Copyright (C) 2022 MingYang Software Technology.
// -------------------------------------------------

#include "./page_popup_session.h"

#include <windowsx.h>
#include "blinkit/win/page_popup_host_window.h"

namespace BlinKit {

static std::unordered_map<HWND, PagePopupHostWindow *> g_popups;

bool PagePopupSession::ForwardMouseMessage(HWND hParent, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &result)
{
    if (nullptr == m_host)
        return false;

    HWND hPopup = *m_host;

    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
    ClientToScreen(hParent, &pt);
    ScreenToClient(hPopup, &pt);

    RECT rc;
    GetClientRect(hPopup, &rc);
    if (!PtInRect(&rc, pt))
        return false;

    m_host->ProcessMessage(hPopup, uMsg, wParam, MAKELPARAM(pt.x, pt.y), result);
    return true;
}

BOOL PagePopupSession::OnNCCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
    PagePopupHostWindow *popup = reinterpret_cast<PagePopupHostWindow *>(lpCreateStruct->lpCreateParams);
    popup->AttachHWND(hwnd);
    g_popups.emplace(hwnd, popup);
    return TRUE;
}

ATOM PagePopupSession::RegisterClass(void)
{
#ifdef NDEBUG
    TCHAR className[32];
    wsprintf(className, TEXT("BkPopup_%x"), GetTickCount()); // Make class name unique.
#endif

    WNDCLASS wc      = { 0 };
    wc.style         = CS_HREDRAW | CS_VREDRAW | CS_DROPSHADOW;
    wc.lpfnWndProc   = WndProc;
    wc.hInstance     = theModule;
    wc.hCursor       = LoadCursor(nullptr, IDC_ARROW);
    wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
#ifdef NDEBUG
    wc.lpszClassName = className;
#else
    wc.lpszClassName = TEXT("BkPopup");
#endif

    return ::RegisterClass(&wc);
}

void PagePopupSession::Start(HWND hParent, PagePopupHostWindow *host)
{
    ASSERT(nullptr == m_host);
    m_host = host;

    static const ATOM s_atom = RegisterClass();
    ASSERT(0 != s_atom);

    CreateWindowEx(WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW, MAKEINTATOM(s_atom), nullptr, WS_POPUP,
        0, 0, 100, 100, hParent, nullptr, theModule, host);
}

void PagePopupSession::Stop(void)
{
    HWND hPopup = *m_host;
    m_host = nullptr;

    DestroyWindow(hPopup);
    g_popups.erase(hPopup);
}

LRESULT CALLBACK PagePopupSession::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (PagePopupHostWindow *popup = zed::query_value(g_popups, hWnd, nullptr))
    {
        LRESULT r = 0;
        if (popup->ProcessMessage(hWnd, uMsg, wParam, lParam, r))
            return r;
    }

    if (WM_NCCREATE == uMsg)
        HANDLE_WM_NCCREATE(hWnd, wParam, lParam, OnNCCreate);
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

} // namespace BlinKit
